/**
 *Copyright (c) 2024 watereyes
 * safetymanagement is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.scene.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.koron.common.bean.StaffBean;
import com.koron.common.dfs.FastDFSClientWrapper;
import com.koron.common.domain.DataBean;
import com.koron.common.generator.DefaultIdGenerator;
import com.koron.common.util.DocConverterUtils;
import com.koron.scene.bean.ProjectPlanBean;
import com.koron.scene.bean.ProjectRealBean;
import com.koron.scene.mapper.ProjectSafetyInvestmentMapper;
import com.koron.scene.service.api.ProjectSafetyInvestmentService;
import com.koron.scene.utils.BusinessCode;

import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.swan.bean.MessageBean;



import java.math.BigDecimal;
import java.util.*;

@SuppressWarnings("deprecation")
@Service
public class ProjectSafetyInvestmentServiceImpl implements ProjectSafetyInvestmentService {
    private final static  Logger logger = LoggerFactory.getLogger(ProjectSafetyInvestmentServiceImpl.class);

    @Autowired
    private FastDFSClientWrapper fastDFSClientWrapper;

    @Autowired
    private DocConverterUtils docConverterUtils;

    @Override
    public MessageBean queryForList(Integer year, String projectId, String enterpriseId, Integer page, Integer pageSize) {
        MessageBean<DataBean<Map>> msg = new MessageBean<>();
        try (SessionFactory factory = new SessionFactory()) {
            ProjectSafetyInvestmentMapper mapper = factory.getMapper(ProjectSafetyInvestmentMapper.class);
            // 查询
            Map map = new HashMap();
            map.put("year", year);
            map.put("projectId", projectId);
            map.put("enterpriseId", enterpriseId);
            page = (page == null || page < 1) ? 1 : page;
            pageSize = (pageSize == null || pageSize < 1) ? 10 : pageSize;
            int pageStart = (page - 1) * pageSize;
            map.put("pageStart", pageStart);
            map.put("pageStop", pageSize);
            List<Map> list = mapper.queryForList(map);
            DataBean<Map> dataBean = new DataBean<>();
            dataBean.setList(list);
            dataBean.setPageSize(pageSize);
            dataBean.setPageNo(page);
            // 总条数
            Integer totalNumber = mapper.countQueryForList(map);
            int num = totalNumber / pageSize;
            // 总页数
            Integer totalPage = totalNumber % pageSize == 0 ? num : num + 1;
            dataBean.setTotalNumber(totalNumber);
            dataBean.setTotalPage(totalPage);
            msg.setData(dataBean);
            msg.setCode(BusinessCode.SUCCESS.getCode());
            msg.setDescription(BusinessCode.SUCCESS.getDescription());
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }
        return msg;
    }

    @Override
    public MessageBean queryById(String id) {
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        if (StringUtils.isEmpty(id)) {
            msg.setCode(BusinessCode.INSUFFICIENT_PARAM.getCode());
            msg.setDescription(BusinessCode.INSUFFICIENT_PARAM.getDescription());
            return msg;
        }
        try (SessionFactory factory = new SessionFactory()) {
            ProjectSafetyInvestmentMapper mapper = factory.getMapper(ProjectSafetyInvestmentMapper.class);
            Map map = mapper.queryById(id);
            if (map == null) {
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription("没有查询到该安全计划！");
            } else {
                // 根据 相关方安全投入计划id 查询 相关方安全投入实际
                map.put("reals", mapper.queryRealListByPlanid(id));
                msg.setData(map);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }
        return msg;
    }

    @Override
    public MessageBean delete(String id) {
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        if (StringUtils.isEmpty(id)) {
            msg.setCode(BusinessCode.INSUFFICIENT_PARAM.getCode());
            msg.setDescription(BusinessCode.INSUFFICIENT_PARAM.getDescription());
            return msg;
        }
        SessionFactory factory = new SessionFactory();
        try {
            ProjectSafetyInvestmentMapper mapper = factory.getMapper(ProjectSafetyInvestmentMapper.class);
            int i = mapper.delete(id);
            if (i != 1) {
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription("该安全计划已经失效，请刷新页面!");
                factory.close(false);
                return msg;
            }
            // 根据 相关方安全投入计划id 查询 相关方安全投入实际
            List<Map> reals = mapper.queryRealListByPlanid(id);
            // 根据 相关方安全投入计划id 删除 相关方安全投入实际
            i = mapper.deleteRealByPlanid(id);
            if (i != reals.size()) {
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription("删除安全计划失败!");
                factory.close(false);
                return msg;
            }
            factory.close();
        } catch (Exception e) {
            factory.close(false);
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }finally {
            if (factory != null) {
                factory.close();
            }
        }
        return msg;
    }

    @Override
    public MessageBean insert(StaffBean user, String projectId, String enterpriseId,
                              ProjectPlanBean planBean, ProjectRealBean realBean) {
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        // 参数校验
        if (StringUtils.isEmpty(projectId) || StringUtils.isEmpty(enterpriseId)
                || StringUtils.isEmpty(planBean.getContributoryProject()) || StringUtils.isEmpty(planBean.getContributoryProjectName())
                || planBean.getPlanTime() == null || planBean.getPlanMoney() == null
                || StringUtils.isEmpty(planBean.getPersonCharge()) || StringUtils.isEmpty(planBean.getPersonChargeName())) {
            msg.setCode(BusinessCode.INSUFFICIENT_PARAM.getCode());
            msg.setDescription(BusinessCode.INSUFFICIENT_PARAM.getDescription());
            return msg;
        }
        if (user == null) {
            msg.setCode(BusinessCode.NO_LOGIN.getCode());
            msg.setDescription(BusinessCode.NO_LOGIN.getDescription());
            return msg;
        }
        SessionFactory factory = new SessionFactory();
        try {
            ProjectSafetyInvestmentMapper mapper = factory.getMapper(ProjectSafetyInvestmentMapper.class);
            // 新增 相关方安全投入计划
            String planId = insertPlan(planBean, user, projectId, enterpriseId, mapper);
            // 新增 相关方安全投入实际
            insertReal(projectId, enterpriseId, planId, realBean, mapper);
            factory.close();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            factory.close(false);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }
        return msg;
    }

    @Override
    public MessageBean update(StaffBean user, String projectId, String enterpriseId,
                              ProjectPlanBean planBean, ProjectRealBean realBean) {
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        // 参数校验
        if (StringUtils.isEmpty(projectId) || StringUtils.isEmpty(enterpriseId)
                || StringUtils.isEmpty(planBean.getContributoryProject()) || StringUtils.isEmpty(planBean.getContributoryProjectName())
                || planBean.getPlanTime() == null || planBean.getPlanMoney() == null
                || StringUtils.isEmpty(planBean.getPersonCharge()) || StringUtils.isEmpty(planBean.getPersonChargeName())
                || StringUtils.isEmpty(planBean.getId())) {
            msg.setCode(BusinessCode.INSUFFICIENT_PARAM.getCode());
            msg.setDescription(BusinessCode.INSUFFICIENT_PARAM.getDescription());
            return msg;
        }
        if (user == null) {
            msg.setCode(BusinessCode.NO_LOGIN.getCode());
            msg.setDescription(BusinessCode.NO_LOGIN.getDescription());
            return msg;
        }
        SessionFactory factory = new SessionFactory();
        try {
            ProjectSafetyInvestmentMapper mapper = factory.getMapper(ProjectSafetyInvestmentMapper.class);
            // 修改 相关方安全投入计划
            updatePlan(planBean, user, mapper);
            // 保存 相关方安全投入实际
            saveReal(projectId, enterpriseId, planBean.getId(), realBean, mapper);
            factory.close();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            factory.close(false);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }
        return msg;
    }

    @Override
    public List<Map> exportQueryForList(Integer year) {
        List<Map> list = null;
        try (SessionFactory factory = new SessionFactory()) {
            ProjectSafetyInvestmentMapper mapper = factory.getMapper(ProjectSafetyInvestmentMapper.class);
            // 查询
            Map map = new HashMap();
            map.put("year", year);
            list = mapper.exportQueryForList(map);
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }
        return list;
    }

    /**
     * 新增 相关方安全投入计划
     *
     * @param planBean
     * @param user
     * @param projectId    项目id
     * @param enterpriseId 相关方id
     * @param mapper
     * @return
     * @throws Exception
     */
    private String insertPlan(ProjectPlanBean planBean, StaffBean user,
                              String projectId, String enterpriseId,
                              ProjectSafetyInvestmentMapper mapper) throws Exception {
        String id = DefaultIdGenerator.getInstance().generateLongId();
        planBean.setId(id);
        planBean.setProjectId(projectId);
        planBean.setEnterpriseId(enterpriseId);
        Date date = new Date();
        planBean.setAddTime(date);
        planBean.setAddUser(user.getCode());
        planBean.setAddUserName(user.getName());
        planBean.setUpdateTime(date);
        planBean.setUpdateUser(user.getCode());
        planBean.setUpdateUserName(user.getName());
        mapper.insertPlan(planBean);
        return id;
    }

    /**
     * 新增 相关方安全投入实际
     *
     * @param projectId    项目id
     * @param enterpriseId 相关方id
     * @param planId       相关方安全投入计划id
     * @param realBean
     * @param mapper
     */
    private void insertReal(String projectId, String enterpriseId, String planId,
                            ProjectRealBean realBean, ProjectSafetyInvestmentMapper mapper) throws Exception {
        // 新增 相关方安全投入实际
        if (realBean != null) {
            // 实际金额
            List<BigDecimal> realityMoneys = realBean.getRealityMoneys();
            if (realityMoneys != null && realityMoneys.size() > 0) {
                int num = realityMoneys.size();
                // 投入明细
                List<String> contributoryDetails = realBean.getContributoryDetails();
                // 实际投入时间
                List<Date> realTimes = realBean.getRealTimes();
                // 效果评估
                List<String> effectAppraisals = realBean.getEffectAppraisals();
                // 责任人
                List<String> personCharges = realBean.getPersonCharges();
                // 责任人名称
                List<String> personChargeNames = realBean.getPersonChargeNames();
                // 备注
                List<String> remarks = realBean.getRemarks();
                // 附件 字符串list
                List<String> accessorys = realBean.getAccessorys();
                // 附件 list
                List<MultipartFile> files = realBean.getFiles();
                int filesNum = 0;
                if (files != null) {
                    filesNum = files.size();
                }
                List<Map> insertList = new LinkedList<>();
                Map map;
                JSONObject jsonObject;
                MultipartFile file;
                for (int i = 0; i < num; i++) {
                    map = new HashMap();
                    map.put("id", DefaultIdGenerator.getInstance().generateLongId());
                    map.put("projectId", projectId);
                    map.put("enterpriseId", enterpriseId);
                    map.put("projectPlanId", planId);
                    map.put("contributoryDetail", contributoryDetails.get(i));
                    map.put("realTime", realTimes.get(i));
                    map.put("realityMoney", realityMoneys.get(i));
                    map.put("effectAppraisal", effectAppraisals.get(i));
                    map.put("personCharge", personCharges.get(i));
                    map.put("personChargeName", personChargeNames.get(i));
                    map.put("remark", remarks.get(i));
                    if (i < filesNum && files.get(i) != null) {
                        file = files.get(i);
                        jsonObject = new JSONObject();
                        jsonObject.put("filename", file.getOriginalFilename());
                        jsonObject.put("fileUrl", fastDFSClientWrapper.uploadFile(file));
                        map.put("accessorys", JSON.toJSONString(jsonObject));
//                        File pdfFile = DocConverterUtils.converter(file);
                        String pdfPath =docConverterUtils.converterUpdate(file);
                        if (pdfPath != null) {
//                            String pdfFilePath = fastDFSClientWrapper.uploadFile(new FileInputStream(pdfFile), pdfFile.length(), FilenameUtils.getExtension(pdfFile.getName()));
                            JSONObject object = new JSONObject();
                            object.put("filename", file.getOriginalFilename());
                            object.put("fileUrl", pdfPath);
                            map.put("previewAccessorys", JSON.toJSONString(object));
                        } else {
                            map.put("previewAccessorys", JSON.toJSONString(jsonObject));
                        }
                    } else {
                        map.put("accessorys", "");
                        map.put("previewAccessorys", "");
                    }
                    insertList.add(map);
                }
                mapper.insertReal(insertList);
            }
        }
    }

    /**
     * 修改 相关方安全投入计划
     *
     * @param planBean
     * @param user
     * @param mapper
     */
    private void updatePlan(ProjectPlanBean planBean, StaffBean user, ProjectSafetyInvestmentMapper mapper) {
        planBean.setUpdateUser(user.getCode());
        planBean.setUpdateUserName(user.getName());
        planBean.setUpdateTime(new Date());
        mapper.updatePlan(planBean);
    }


    /**
     * 保存 相关方安全投入实际
     *
     * @param projectId    项目id
     * @param enterpriseId 相关方id
     * @param planId       相关方安全投入计划id
     * @param realBean
     * @param mapper
     */
    private void saveReal(String projectId, String enterpriseId, String planId,
                          ProjectRealBean realBean, ProjectSafetyInvestmentMapper mapper) throws Exception {
        // 根据 相关方安全投入计划id 查询 相关方安全投入实际
        List<Map> realList = mapper.queryRealListByPlanid(planId);
        if (realBean == null) {
            // 根据 相关方安全投入计划id 删除 相关方安全投入实际
            mapper.deleteRealByPlanid(planId);
            // 删除文件
            Optional.ofNullable(realList)
                    .map(reals -> {
                        for (Map map : reals) {
                            Optional.ofNullable(map.get("accessorys"))
                                    .map(obj -> obj.toString())
                                    .map(accessorys -> {
                                        if (StringUtils.isNotEmpty(accessorys)) {
                                            Optional.ofNullable(JSON.parseObject(accessorys).get("fileUrl"))
                                                    .map(fileUrl -> {
                                                        fastDFSClientWrapper.deleteFile(fileUrl.toString());
                                                        return null;
                                                    });
                                        }
                                        return null;
                                    });
                        }
                        return null;
                    });
        } else {
            List<String> realIds = realBean.getRealIds();
            if (realIds != null && realIds.size() > 0) {
                int num = realIds.size();
                // 实际金额
                List<BigDecimal> realityMoneys = realBean.getRealityMoneys();
                // 投入明细
                List<String> contributoryDetails = realBean.getContributoryDetails();
                // 实际投入时间
                List<Date> realTimes = realBean.getRealTimes();
                // 效果评估
                List<String> effectAppraisals = realBean.getEffectAppraisals();
                // 责任人
                List<String> personCharges = realBean.getPersonCharges();
                // 责任人名称
                List<String> personChargeNames = realBean.getPersonChargeNames();
                // 备注
                List<String> remarks = realBean.getRemarks();
                // 附件 字符串list
                List<String> accessorys = realBean.getAccessorys();
                // 预览附件 字符串list
                List<String> previewAccessorys = realBean.getPreviewAccessorys();
                // 附件 list
                List<MultipartFile> files = realBean.getFiles();
                int filesNum = 0;
                if (files != null) {
                    filesNum = files.size();
                }
                // 新增 list
                List<Map> insertList = new LinkedList<>();
                // 文件fileUrl list
                List<String> fileUrls = new LinkedList<>();
                List<String> filePreUrls = new LinkedList<>();
                String fileUrl;
                String filePreUrl;
                Map map;
                JSONObject jsonObject;
                MultipartFile file;
                for (int i = 0; i < num; i++) {
                    fileUrl = accessorys.get(i);
                    if (StringUtils.isNotEmpty(fileUrl)) {
                        jsonObject = JSON.parseObject(fileUrl);
                        if (jsonObject.get("fileUrl") != null) {
                            fileUrls.add(jsonObject.get("fileUrl").toString());
                        }
                    }
                    filePreUrl=previewAccessorys.get(i);
                    if (StringUtils.isNotEmpty(filePreUrl)) {
                        jsonObject = JSON.parseObject(filePreUrl);
                        if (jsonObject.get("fileUrl") != null) {
                            filePreUrls.add(jsonObject.get("fileUrl").toString());
                        }
                    }
                    map = new HashMap();
                    map.put("projectId", projectId);
                    map.put("enterpriseId", enterpriseId);
                    map.put("projectPlanId", planId);
                    map.put("contributoryDetail", contributoryDetails.get(i));
                    map.put("realTime", realTimes.get(i));
                    map.put("realityMoney", realityMoneys.get(i));
                    map.put("effectAppraisal", effectAppraisals.get(i));
                    map.put("personCharge", personCharges.get(i));
                    map.put("personChargeName", personChargeNames.get(i));
                    map.put("remark", remarks.get(i));
                    if (i < filesNum && files.get(i) != null) {
                        file = files.get(i);
                        jsonObject = new JSONObject();
                        jsonObject.put("filename", file.getOriginalFilename());
                        jsonObject.put("fileUrl", fastDFSClientWrapper.uploadFile(file));
                        map.put("accessorys", JSON.toJSONString(jsonObject));
//                        File pdfFile = DocConverterUtils.converter(file);
                        String pdfPath=docConverterUtils.converterUpdate(file);
                        if (pdfPath != null) {
//                            String pdfFilePath = fastDFSClientWrapper.uploadFile(new FileInputStream(pdfFile), pdfFile.length(), FilenameUtils.getExtension(pdfFile.getName()));
                            JSONObject object = new JSONObject();
                            object.put("filename", file.getOriginalFilename());
                            object.put("fileUrl", pdfPath);
                            map.put("previewAccessorys", JSON.toJSONString(object));
                        } else {
                            map.put("previewAccessorys", JSON.toJSONString(jsonObject));
                        }
                    } else {
                        if (StringUtils.isNotEmpty(realIds.get(i))) {
                            map.put("accessorys", accessorys.get(i));
                            map.put("previewAccessorys", previewAccessorys.get(i));
                        } else {
                            map.put("accessorys", "");
                            map.put("previewAccessorys", "");
                        }

                    }
                    map.put("id", DefaultIdGenerator.getInstance().generateLongId());
                    insertList.add(map);
                }
                // 根据 相关方安全投入计划id 删除 相关方安全投入实际
                mapper.deleteRealByPlanid(planId);
                // 新增
                if (insertList.size() > 0) {
                    mapper.insertReal(insertList);
                }
                // 删除文件
                Optional.ofNullable(realList)
                        .map(reals -> {
                            for (Map m : reals) {
                                Optional.ofNullable(m.get("accessorys"))
                                        .map(obj -> obj.toString())
                                        .map(acc -> {
                                            if (StringUtils.isNotEmpty(acc)) {
                                                Optional.ofNullable(JSON.parseObject(acc).get("fileUrl"))
                                                        .map(url -> {
                                                            // 删除不在 fileUrls list中的附件
                                                            if (filter(url.toString(), fileUrls) == false) {
                                                                fastDFSClientWrapper.deleteFile(url.toString());
                                                            }
                                                            return null;
                                                        });
                                            }
                                            return null;
                                        });
                                Optional.ofNullable(m.get("previewAccessorys"))
                                        .map(obj -> obj.toString())
                                        .map(acc -> {
                                            if (StringUtils.isNotEmpty(acc)) {
                                                Optional.ofNullable(JSON.parseObject(acc).get("fileUrl"))
                                                        .map(url -> {
                                                            // 删除不在 fileUrls list中的附件
                                                            if (filter(url.toString(), filePreUrls) == false) {
                                                                fastDFSClientWrapper.deleteFile(url.toString());
                                                            }
                                                            return null;
                                                        });
                                            }
                                            return null;
                                        });
                            }
                            return null;
                        });
            }
        }
    }

    /**
     * 判断url 是否在list中存在
     *
     * @param url
     * @param list
     * @return
     */
    private boolean filter(String url, List<String> list) {
        if (list == null || list.size() == 0) {
            return false;
        }
        for (String str : list) {
            if (url.equals(str)) {
                return true;
            }
        }
        return false;
    }
}
